package com.zmn.oms.dubbo.impl.zmn.normal.order;

import com.alibaba.fastjson.JSON;
import com.zmn.biz.engineer.common.dro.discount.EngineerDiscountDRO;
import com.zmn.biz.engineer.dubbo.interfaces.discount.EngineerDiscountListRemoteService;
import com.zmn.oms.common.constant.DiscountConsts;
import org.apache.dubbo.config.annotation.Reference;
import com.github.ltsopensource.core.domain.Job;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto.ResultDTO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.dms.common.enums.DiscountTypeEnums;
import com.zmn.manager.lts.interfaces.task.TaskManager;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.common.constant.MessageRuleIdConsts;
import com.zmn.oms.common.constant.TriggerAmountChangeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.common.work.OrderDetailDiscountDRO;
import com.zmn.oms.dubbo.dto.zmn.order.OrderQuotationDRO;
import com.zmn.oms.dubbo.dto.zmn.order.OrderQuotationDiscountDRO;
import com.zmn.oms.dubbo.dto.zmn.serviceitem.OrderServiceItemDRO;
import com.zmn.oms.dubbo.interfaces.zmn.normal.order.OrderWorkQuotationRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.manager.utils.TaskConsts;
import com.zmn.oms.model.bo.orderamount.DiscountConditionParamsDIO;
import com.zmn.oms.model.bo.orderamount.OrderAmountDIO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.discount.ZsOrderDiscountBService;
import com.zmn.oms.zmn.normal.business.interfaces.serviceitem.ZsNormalOrderServiceItemBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service(loadbalance = "roundrobin", timeout = 20000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class OrderWorkQuotationRemoteServiceImpl implements OrderWorkQuotationRemoteService {
    @Autowired
    private ZsOrderDiscountBService zsOrderDiscountBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private ZsNormalOrderServiceItemBService zsNormalOrderServiceItemBService;
    @Autowired
    private OrderDiscountCalcBService orderDiscountCalcBService;
    @Autowired
    private OrderDiscountService orderDiscountService;
    @Autowired
    private OrderServiceItemService orderServiceItemService;
    @Autowired
    private TaskManager taskManager;
    @Autowired
    private RedisManager redisManager;

   // @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    //private SaleApplyCountModifyService saleApplyCountModifyService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerDiscountListRemoteService engineerDiscountListRemoteService;


    @Override
    public ResponseDTO<OrderQuotationDRO> getOrderQuotationDiscountById(Long orderId, Long workId) {
        log.info("#oms#orderId={} 根据id查询订单优惠信息 getOrderQuotationDiscountById", orderId);
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (dbOrderWork == null) {
            return ResponseDTO.fail("not find order!");
        }

        // 订单优惠明细
        List<OrderDiscount> discountList = zsOrderDiscountBService.listByOrderId(orderId);
        List<OrderDetailDiscountDRO> orderDetailDiscountList = BeanMapper.mapList(discountList, OrderDetailDiscountDRO.class);
        if (CollectionUtil.isNotNullOrEmpty(orderDetailDiscountList)) {
            orderDetailDiscountList.forEach(e -> e.setCategName(StringUtils.defaultString(DiscountTypeEnums.getSubName(e.getCateg()))));
        }
        OrderQuotationDRO orderQuotationDRO = new OrderQuotationDRO();
        orderQuotationDRO.setOrderId(dbOrderWork.getOrderId());
        orderQuotationDRO.setMasterAmount(dbOrderWork.getMasterAmount());
        orderQuotationDRO.setOriginalAmount(dbOrderWork.getOriginalAmount());
        orderQuotationDRO.setTotalAmount(dbOrderWork.getTotalAmount());
        orderQuotationDRO.setOrderDiscountList(orderDetailDiscountList);
        orderQuotationDRO.setPayDiscountAmount(dbOrderWork.getPayDiscountAmount());
        return ResponseDTO.success(orderQuotationDRO);
    }

    @Override
    public ResponseDTO<Boolean> applyOrderDiscountNoticeById(Long orderId, Long workId) {
        log.info("#oms#orderId={} 申请优惠消息通知 applyOrderDiscountNoticeById", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (orderWork == null) {
            return ResponseDTO.fail("not find order!");
        }

        Job job = new Job();
        job.setTaskId(TaskConsts.TASK_ID_SEND_MESSAGE_JOB + ":" + orderId);
        job.setParam("orderId", String.valueOf(orderId));
        job.setParam("workId", String.valueOf(workId));
        job.setParam("ruleId", String.valueOf(MessageRuleIdConsts.ZMN_MSG_RULEID_QUOTATION_CONFIRM));
        job.setParam("nodeMark", String.valueOf(MessageRuleIdConsts.MESSAGE_GLOBAL_QUOTATION_CONFIRM_NODE_MARK));
        job.setParam(TaskManager.SHARD_FIELD, TaskConsts.TASK_ID_SEND_MESSAGE_JOB);
        Date date = DateUtil.addSecond(DateUtil.getNow(), 30);
        ResultDTO result = taskManager.submitTask(job, -1, DateUtil.dateFormatToString(date, DateUtil.FORMAT_DEFAULT));
        if (!result.getStatusBool()) {
            log.error("#oms#send_message_job# job submit fail...");
            return ResponseDTO.success(false);
        }
        return ResponseDTO.success(true);
    }

    @Override
    public ResponseDTO<OrderQuotationDiscountDRO> getQuotationMaxDiscountAmount(Long orderId, Long workId) {
        log.info("#oms#orderId={} 开始获取订单渠道是否有优惠及优惠金额 getQuotationMaxDiscountAmount", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (orderWork == null) {
            return ResponseDTO.fail("not find order!");
        }
        try {
            List<OrderDiscount> orderDiscounts = Lists.newArrayList();
            if (NumberUtil.isNotNullOrZero(orderWork.getDiscountAmount())) {
                orderDiscounts = orderDiscountService.listByOrderId(orderId);
            }
            ReCalcOrderAmountDIO calcOrderAmountDIO = new ReCalcOrderAmountDIO();
            calcOrderAmountDIO.setOrderAmountDIO(BeanMapper.map(orderWork, OrderAmountDIO.class));
            calcOrderAmountDIO.setDiscountConditionParamsDIO(BeanMapper.map(orderWork, DiscountConditionParamsDIO.class));
            calcOrderAmountDIO.setOrderDiscountList(orderDiscounts);

            Integer artificialMaxDiscount = orderDiscountCalcBService.getArtificialMaxDiscount(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT, calcOrderAmountDIO);
            OrderQuotationDiscountDRO orderQuotationDiscount = new OrderQuotationDiscountDRO();
            orderQuotationDiscount.setMaxDiscountAmount(artificialMaxDiscount);
            orderQuotationDiscount.setHaveAmount(NumberUtil.isNotNullOrZero(artificialMaxDiscount) ? GlobalConsts.YES : GlobalConsts.NO);
            orderQuotationDiscount.setOrderId(orderId);
            return ResponseDTO.success(orderQuotationDiscount);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    @Override
    public ResponseDTO<Integer> getPromId(Long orderId,Long workId) {
        log.info("#oms#orderId={} 开始获取优惠券Id getPromId", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (orderWork == null) {
            return ResponseDTO.fail("not find order!");
        }
        try {
            List<OrderDiscount> orderDiscounts = Lists.newArrayList();
            if (NumberUtil.isNotNullOrZero(orderWork.getDiscountAmount())) {
                orderDiscounts = orderDiscountService.listByOrderId(orderId);
            }
            ReCalcOrderAmountDIO calcOrderAmountDIO = new ReCalcOrderAmountDIO();
            calcOrderAmountDIO.setOrderAmountDIO(BeanMapper.map(orderWork, OrderAmountDIO.class));
            calcOrderAmountDIO.setDiscountConditionParamsDIO(BeanMapper.map(orderWork, DiscountConditionParamsDIO.class));
            calcOrderAmountDIO.setOrderDiscountList(orderDiscounts);

            Integer promId = orderDiscountCalcBService.getPromId(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT, calcOrderAmountDIO);

            return ResponseDTO.success(promId);

        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    @Override
    public ResponseDTO<Integer> getArtificialOffer(Long orderId) {
        List<OrderDiscount> discounts = orderDiscountService.listByOrderIdSrcMaster(orderId);
        // 获取人工优惠金额
        Integer discountAmount = discounts.stream().filter(discount -> Objects.equals(discount.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL)).mapToInt(OrderDiscount::getAmount).sum();
        return ResponseDTO.success(discountAmount);
    }

    @Override
    public ResponseDTO<List<OrderServiceItemDRO>> getQuotationServiceItemsById(Long orderId, Long workId) {
        List<OrderServiceItem> orderServiceItems = zsNormalOrderServiceItemBService.listByOrderId(orderId);
        // 转换
        List<OrderServiceItemDRO> orderServiceItemDROS = BeanMapper.mapList(orderServiceItems, OrderServiceItemDRO.class);
        return ResponseDTO.success(orderServiceItemDROS);
    }

    @Override
    public ResponseDTO checkOrderCanApplyDiscount(Long orderId, Long workId) {
        log.info("#oms#orderId={} 能否申请优惠 checkOrderCanApplyDiscount", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (orderWork == null) {
            return ResponseDTO.fail("not find order!");
        }
        Integer masterId = orderWork.getMasterId();
        if (NumberUtil.isNullOrZero(masterId)) {
            return ResponseDTO.fail("not find masterId!");
        }

        // 是否有服务项目
        List<OrderServiceItem> orderServiceItemList = orderServiceItemService.listByOrderId(orderWork.getOrderId());
        if (CollectionUtils.isEmpty(orderServiceItemList)) {
            return ResponseDTO.fail("not find items price!");
        }

        // 获取师傅优惠次数
        // todo fubiao
        log.info("checkOrderCanApplyDiscount#getDiscountByEngineerId 入参 [{}]",masterId);
        ResponseDTO<EngineerDiscountDRO> applyCountResp = engineerDiscountListRemoteService.getDiscountByEngineerId(masterId);
        log.info("checkOrderCanApplyDiscount#getDiscountByEngineerId 出参 [{}]", JSON.toJSONString(applyCountResp));
        log.info("#oms#getSaleApplyCountByEngineer#orderId={},获取师傅优惠次数入参masterId={},出参数={}", orderWork.getOrderId(), masterId, applyCountResp);
        if (!applyCountResp.isSuccess()) {
            return ResponseDTO.fail("获取优惠次数失败!");
        }

        // 检查订单工程师是否申请过优惠，已申请过优惠，可以申请优惠
        String redisKey = String.format(RedisKeyConsts.MASTER_APPLY_DISCOUNT_KEY, String.valueOf(orderWork.getOrderId()), masterId);
        boolean haveApplyDiscount = redisManager.exists(redisKey);
        if (haveApplyDiscount) {
            return ResponseDTO.success();
        }

        EngineerDiscountDRO saleApplyCountDRO = applyCountResp.getData();
        // 超过申请优惠上限，可以申请优惠
        boolean notApplyDiscount = Objects.equals(saleApplyCountDRO.getUsedCount(), saleApplyCountDRO.getUpperLimitCount());
        if (notApplyDiscount) {
            return ResponseDTO.fail("申请优惠次数已达到上限!");
        }

        return ResponseDTO.success();
    }


}
